import * as _ from 'lodash';
import {observable, action} from 'mobx';
import {SudokuBean, SudokuController} from '../../../model/sudoku/Sudoku';
import {AdAppPositionController} from '../../../model/ad/adPosition/AdAppPositionController'
import {FormStore, ListStore, FieldItem, isRequired, isSelectRequired, toJSDeep} from '../../common/store/Store';
import {treeFormatNode, toPlainObjectDeep, loadArea} from '../../../utils/Utils';

interface SudokuDto<T> extends SudokuBean<FieldItem> {
    filterAreaIds?: Array<string> | T;
    selectSudokuOption?: Array<any> | T;
}

interface SudokuSearchDto<T> {
    platformType: string | T;
}

const sudokuController = new SudokuController();
const adAppPositionController = new AdAppPositionController();

export class SudokuStoreFields implements SudokuDto<FieldItem> {
    constructor(type = 'add') {
        if (type === 'edit') {
            _.forEach(this, (field: FieldItem, key: string) => {
                if (field.hasFeedback === true) {
                    field.validateStatus = 'success';
                }
            })
        }
    }

    id: FieldItem = new FieldItem({
        value: null,
    });

    platformType: FieldItem = new FieldItem({
        value: -1,
        hasFeedback: true,
        required: true,
        option: [{
            type: -1,
            name: '请选择',
            title: '请选择',
            description: '请选择'
        }]
    });

    category: FieldItem = new FieldItem({
        value: -1,
        hasFeedback: true,
        required: true,
        disabled: true,
        option: [{
            type: -1,
            name: '请选择'
        }]
    });

    areaIds: FieldItem = new FieldItem({
        value: [],
        hasFeedback: true,
        required: true
    });

    filterAreaIds: FieldItem = new FieldItem({
        value: []
    });

    sudokuOption: FieldItem = new FieldItem({
        value: [],
        hasFeedback: true,
        required: true,
        disabled: true,
        option: []
    });

    selectSudokuOption: FieldItem = new FieldItem({
        value: []
    })
}

export class SudokuSearchStoreFields implements SudokuSearchDto<FieldItem> {
    platformType: FieldItem = new FieldItem({
        value: -1,
        option: [{
            type: -1,
            name: '请选择',
            title: '请选择',
            description: '请选择'
        }]
    });

    category: FieldItem = new FieldItem({
        value: -1,
        option: [{
            type: -1,
            name: '请选择'
        }]
    });

    areaIds: FieldItem = new FieldItem({
        value: null
    });
}

const addDefaultFields: any = toPlainObjectDeep(new SudokuStoreFields());

const searchDefaultFields: any = toPlainObjectDeep(new SudokuSearchStoreFields());

export class SudokuBaseFormStore extends FormStore<SudokuStoreFields, SudokuDto<any>> {
    @observable confirmLoading: boolean = false;

    @action
    changeConfirmLoading(params) {
        this.confirmLoading = params;
    }

    validators = {
        areaIds: [isRequired],
        platformType: [isSelectRequired],
        sudokuOption: [isRequired],
        category: [isSelectRequired]
    };

    @action
    getCategory() {
        return sudokuController.getSudokuCategory().then((data) => {
            this.fields.category.option = _.cloneDeep(toJSDeep(this.fields.category.option)).concat(data.result);
            return data;
        });
    }

    @action
    getPlatForm() {
        return platFormService.then((data) => {
            this.fields.platformType.option = _.cloneDeep(toJSDeep(this.fields.platformType.option)).concat(data);
            return data;
        });
    }

    @action
    selectPlatForm() {
        this.clearCategory();
        this.clearSudokuOption();
        if (_.toString(this.fields.platformType.value) !== '-1') {
            this.getCategory().then(() => {
                this.changeField('category', {disabled: false});
            })
        }
    }

    @action
    selectCategory() {
        this.clearSudokuOption();

        if (_.toString(this.fields.category.value) !== '-1') {
            const platform = findPlatFormNameById(this.fields.platformType);
            const category = this.fields.category.value;

            return this.getSudokuOption({
                appName: 'juhe-app',
                platform: platform,
                category: category
            }).then(action(() => {
                this.changeField('sudokuOption', {disabled: false});
            }));
        }
    }

    @action
    clearPlatForm() {
        this.fields.platformType = _.cloneDeep(this.defaultFields.platformType);
        this.valid('platformType', this.fields.platformType.value.toString());
    }

    @action
    clearCategory() {
        this.fields.category = _.cloneDeep(this.defaultFields.category);
        this.valid('category', this.fields.category.value.toString());
    }

    @action
    clearSudokuOption() {
        this.fields.sudokuOption = _.cloneDeep(this.defaultFields.sudokuOption);
        this.fields.selectSudokuOption = _.cloneDeep(this.defaultFields.selectSudokuOption)
        this.valid('sudokuOption', this.fields.sudokuOption.value, !this.fields.sudokuOption.required);
    }

    @action
    getSudokuOption(params: {
        appName: string;
        platform: string;
        category: number;
    }) {
        return sudokuController.getSudokuOptions(params)
            .then(action((data: any) => {
                this.fields.sudokuOption.option = data.result;
                return data;
            }));
    }

    @action
    bindData() {
        this.getPlatForm();
        this.getCategory();
    }

    @action
    getSelectSudokuOption = (SelectSudokuOptionTextArr) => {
        return _.filter(this.fields.sudokuOption.option, (item, key) => {
            return _.some(SelectSudokuOptionTextArr, (_item) => {
                return _item === _.toString(item.text);
            });
        });
    }

    @action
    changeSudokuOptions = (value) => {
        this.valid('sudokuOption', value, !this.fields.sudokuOption.required);
        this.fields.selectSudokuOption.value = this.getSelectSudokuOption(value);
    }

    @action
    changeSelectSudokuOption = (items) => {
        this.fields.selectSudokuOption.value = items;
    }
}

export class Add extends SudokuBaseFormStore {
    defaultFields = _.cloneDeep(addDefaultFields);

    @observable fields: SudokuStoreFields = _.cloneDeep<SudokuStoreFields>(addDefaultFields);

    @action
    load = () => {
        this.bindData();
        this.show();
    }

    @action
    addSudoku = (params: any) => {
        return sudokuController.addSudoku(params);
    }

    sortSelectSudokuOption() {
        const platform = findPlatFormNameById(this.fields.platformType);
        const category = this.fields.category.value;

        const selectSudokuOption = _.cloneDeep(toJSDeep(this.fields.selectSudokuOption.value));

        return _.map(selectSudokuOption, (item, index) => {
            return _.assign({}, item, {
                sort: index + 1,
                appName: 'juhe-app',
                platform: platform,
                category: category
            })
        })
    }

    getValuesWithName() {
        let data;

        let filterAreaIds = this.fields.filterAreaIds.value;
        let filterVal = [];

        if (filterAreaIds.length > 0 && _.isNumber(filterAreaIds[0])) {
            filterVal = filterAreaIds;
        } else {
            filterVal = _.map(_.filter(toJSDeep(this.fields.filterAreaIds.value), (item: any) => {
                return !!item.props && !item.props.hasOwnProperty('children');
            }), (_item) => {
                return _.parseInt(_item.key);
            });
        }

        const selectSudokuOption = this.sortSelectSudokuOption();

        data = _.assign(this.getValues(), {
            areaIds: filterVal,
            filterAreaIds: [],
            appServiceJson: selectSudokuOption
        });

        return data;
    }
}

class Check extends SudokuBaseFormStore {
    @action
    changeSelectSudokuOption = (data) => {
        this.fields.selectSudokuOption.value = data.result;
        this.show();
    }

    load(params) {
        sudokuController.checkSudoku(params)
            .then(this.changeSelectSudokuOption);
    }

    defaultFields = _.cloneDeep(addDefaultFields);

    @observable fields: SudokuStoreFields = _.cloneDeep(addDefaultFields);
}

export class List extends ListStore<SudokuDto<any>> {
    @action
    searchSudoku(params?: any) {
        this._SpiLoading = true;

        sudokuController.searchSudoku(params).then((data) => {
            this.searchCallback(data);
        })
    }

    @action
    load(params: any = {}) {
        this.searchSudoku(params);
    }

    @action
    refresh(search: Search) {
        this.changeState(true);
        search.clearAll();
        search.getPlatForm();
        search.getCategory();
        this.load();
    }
}

class Search extends FormStore<SudokuSearchStoreFields, SudokuSearchDto<any>> {
    load() {
        this.getPlatForm();
        this.getCategory();

    }

    @action
    getCategory() {
        return sudokuController.getSudokuCategory().then((data) => {
            this.fields.category.option = _.cloneDeep(toJSDeep(this.fields.category.option)).concat(data.result);
            return data;
        });
    }

    defaultFields = _.cloneDeep(searchDefaultFields);

    @observable fields: SudokuSearchStoreFields = _.cloneDeep(searchDefaultFields);

    @observable expand: boolean = false;

    @action
    getPlatForm(buId = 1, appId = 1) {
        return platFormService.then((data) => {
            this.fields.platformType.option = _.cloneDeep(toJSDeep(this.fields.platformType.option)).concat(data);
            return data;
        });
    }

    @action
    OnExpand(expand) {
        this.expand = !expand;
    }

    @action
    clearSearch(list: List) {
        this.clearAll();
        this.getPlatForm();
        this.getCategory();
        list.load();
    }

    @action
    clearSearchState() {
        this.expand = false;
        this.clearAll();
        this.getPlatForm();
    }

    getValuesWithName = () => {
        let platform = '', category = '';
        const data: any = this.getValues();

        if (_.toString(data.platformType) !== '-1') {
            platform = findPlatFormNameById(this.fields.platformType);
        }

        if (_.toString(data.category) !== '-1') {
            category = data.category;
        }

        return {
            appName: 'juhe-app',
            platform: platform,
            category: category,
            areaIds: data.areaIds
        };
    }
}

class AreaTreeStore {
    constructor() {
        this.loadAreaTree();
    }

    @observable treeData: Array<any> = [];

    loadAreaTree() {
        loadArea().then(action((data) => {
            this.treeData = treeFormatNode.getTreeNode(data);
        }))
    }
}

const findPlatFormNameById = (platformType: FieldItem) => {
    const platformTypeObj = _.find(platformType.option, (item: any) => {
        const platformTypeId = platformType.value;

        return _.toString(item.type) === _.toString(platformTypeId);
    });

    if (!_.isEmpty(platformTypeObj)) {
        return platformTypeObj.name;
    }

    return '';
}

const platFormFn = async (buId = 1, appId = 1) => {
    const res = await adAppPositionController.getPartnerAppPlatforms({BUId: buId, appId: appId});

    return Promise.resolve(res.result);

}

const platFormService = platFormFn();

export const listStore = new List();
export const addStore = new Add();
export const checkStore = new Check();
export const areaTreeStore = new AreaTreeStore();
export const searchStore = new Search();